package trade

import (
	"bsinpass/go/mpc/blockchain/cfx/cfxerc1155"
	"bsinpass/go/mpc/blockchain/cfx/cfxerc20"
	cfxerc721 "bsinpass/go/mpc/blockchain/cfx/cfxerc721"
	"bsinpass/go/mpc/blockchain/cfx/cfxsponsor"
	"bsinpass/go/mpc/blockchain/cfx/contract"
	"bsinpass/go/mpc/blockchain/client"
	mpcCommon "bsinpass/go/mpc/common"
	"context"
	"fmt"
	"math/big"
	"strings"
	"time"

	// "github.com/sirupsen/logrus"

	"github.com/Conflux-Chain/go-conflux-sdk/types"
	"github.com/Conflux-Chain/go-conflux-sdk/types/cfxaddress"
	"github.com/ethereum/go-ethereum/accounts"

	ethBind "github.com/ethereum/go-ethereum/accounts/abi/bind"
	"github.com/ethereum/go-ethereum/common"
)

var txConf = &mpcCommon.GlobalConf
var txLog = mpcCommon.GetNftLog("trade")

func getAccountAccordAddress(caller string) *accounts.Account {
	if txConf.LocalWallet == nil {
		return nil
	}
	currAccounts := txConf.LocalWallet.Accounts()
	var account *accounts.Account = nil
	for _, tmp := range currAccounts {
		if strings.ToLower(tmp.Address.Hex()) == strings.ToLower(caller) {
			account = &tmp
			break
		}
	}
	return account
}

func getNftContractTransaction(reqChain, contractAddr, caller string) (*contract.Contract, *ethBind.TransactOpts, mpcCommon.NftError) {
	account := getAccountAccordAddress(caller)
	if account == nil {
		txLog.LogE("We can not visit caller address.")
		return nil, nil, mpcCommon.NewError(501)
	}
	keyJson, err := txConf.LocalWallet.Export(*account, txConf.PassWord, txConf.PassWord)
	if err != nil {
		txLog.LogE("Export caller keystore failed! [%v]", err)
		return nil, nil, mpcCommon.NewError(501)
	}
	client, nftErr := client.GetEthClient(reqChain)
	if !mpcCommon.Valid(nftErr) {
		txLog.LogE("Get eth client failed! [%v]", nftErr.ErrorMsg)
		return nil, nil, nftErr
	}
	nftContract, err := contract.NewContract(common.HexToAddress(contractAddr), client)
	if err != nil {
		txLog.LogE("Get nft contract failed! [%v]", err)
		return nil, nil, mpcCommon.NewError(506)
	}
	v, _ := txConf.SupportChains[reqChain]
	opts, err := ethBind.NewTransactorWithChainID(strings.NewReader(string(keyJson)), txConf.PassWord, big.NewInt(int64(v.ChainId)))
	if err != nil {
		txLog.LogE("Create transaction option failed! [%v]", err)
		return nil, nil, mpcCommon.NewError(500)
	}
	return nftContract, opts, mpcCommon.NewError(200)
}

func getNftContractTransactionCfx(reqChain, contractAddr, caller string) (*contract.Contract, *ethBind.TransactOpts, mpcCommon.NftError) {
	account := getAccountAccordAddress(caller)
	if account == nil {
		txLog.LogE("We can not visit caller address.")
		return nil, nil, mpcCommon.NewError(501)
	}
	keyJson, err := txConf.LocalWallet.Export(*account, txConf.PassWord, txConf.PassWord)
	if err != nil {
		txLog.LogE("Export caller keystore failed! [%v]", err)
		return nil, nil, mpcCommon.NewError(501)
	}
	client, nftErr := client.GetEthClient(reqChain)
	if !mpcCommon.Valid(nftErr) {
		txLog.LogE("Get eth client failed! [%v]", nftErr.ErrorMsg)
		return nil, nil, nftErr
	}
	nftContract, err := contract.NewContract(common.HexToAddress(contractAddr), client)
	if err != nil {
		txLog.LogE("Get nft contract failed! [%v]", err)
		return nil, nil, mpcCommon.NewError(506)
	}
	v, _ := txConf.SupportChains[reqChain]
	opts, err := ethBind.NewTransactorWithChainID(strings.NewReader(string(keyJson)), txConf.PassWord, big.NewInt(int64(v.ChainId)))
	if err != nil {
		txLog.LogE("Create transaction option failed! [%v]", err)
		return nil, nil, mpcCommon.NewError(500)
	}
	return nftContract, opts, mpcCommon.NewError(200)
}

func DeployErc20(reqChain, totalsupply, name, symbol, caller, callerprivatekey string) (string, string, mpcCommon.NftError, string, string) {
	tsupply, ok := big.NewInt(0).SetString(totalsupply, 10)
	if !ok {
		txLog.LogE("Input totalsupply [%v] not correct!", totalsupply)
		return "", "", mpcCommon.NewError(405), "", ""
	}
	// get cfx client
	client, nftErr := client.GetCfxClient(reqChain)
	if !mpcCommon.Valid(nftErr) {
		txLog.LogE("Get cfx client failed! [%v]", nftErr.ErrorMsg)
		return "", "", nftErr, "", ""
	}

	accounts := client.AccountManager.List()
	fmt.Println("accounts-----------------11111:\n", accounts)

	for _, account := range accounts {
		client.AccountManager.Delete(account, txConf.PassWord)
		fmt.Println("delete account:", account)
	}

	address, err := txConf.AccountManager.ImportKey(callerprivatekey, txConf.PassWord)
	fmt.Println("import address: ", address)
	if err != nil {
		txLog.LogE("Cfx Import to keystore failed! [%v]", err)
		// return "", mpcCommon.NewError(511)
	}

	accounts = client.AccountManager.List()
	fmt.Println("accounts--------22222:\n", accounts)
	err = client.AccountManager.UnlockDefault(txConf.PassWord)
	if err != nil {
		txLog.LogE("UnlockDefault failed! [%v]", err)
		return "", "", mpcCommon.NewError(511), "", ""
	}

	// if account.GetCfxCurrentAccounts() == nil {
	// 	fmt.Println("Get cfx current account failed!")
	// 	_, err := account.CfxImportAccount(mpcCommon.GlobalConf.PrivateKey)
	// 	if err != nil {
	// 		return "", "", mpcCommon.NewError(509)
	// 	}
	// }
	fmt.Println("deploy from:\n", client.AccountManager.List())
	tx, hash, _, err := cfxerc20.DeployCfxerc20(nil, client, tsupply, name, symbol)
	if err != nil {
		fmt.Println(err)
		return "", "", mpcCommon.NewError(509), "", ""
	}

	// *types.TransactionReceipt
	receipt, err := client.WaitForTransationReceipt(*hash, time.Second)
	if err != nil {
		return "", "", mpcCommon.NewError(510), "", ""
	}

	// logrus.WithFields(logrus.Fields{
	// 	"tx":               tx,
	// 	"hash":             hash,
	// 	"contract address": receipt.ContractCreated,
	// }).Info("deploy token done")

	fmt.Println("deploy hash:\n", hash.String())
	fmt.Println("deploy contract address:\n", receipt.ContractCreated.String())

	outTx := fmt.Sprintf("%v", tx)
	fmt.Println("outTx: ", outTx)
	outRecipt := fmt.Sprintf("%v", receipt)
	fmt.Println("outRecipt: ", outRecipt)
	return hash.String(), receipt.ContractCreated.String(), mpcCommon.NewError(200), outTx, outRecipt
}

func Mint(reqChain, contractAddr, caller, to, tokenid, uri string) (string, mpcCommon.NftError, string, string) {
	tid, ok := big.NewInt(0).SetString(tokenid, 10)
	if !ok {
		txLog.LogE("Input token id [%v] not correct!", tokenid)
		return "", mpcCommon.NewError(403), "", ""
	}
	nftContract, opts, nftErr := getNftContractTransaction(reqChain, contractAddr, caller)
	if !mpcCommon.Valid(nftErr) {
		txLog.LogE("Get nft contract and transaction options failed! [%v]", nftErr.ErrorMsg)
		return "", nftErr, "", ""
	}
	txHash, err := nftContract.Mint(opts, common.HexToAddress(to), tid, uri)
	if err != nil {
		txLog.LogE("Call contract Mint failed! [%v]", err)
		return "", mpcCommon.NewError(502), "", ""
	}
	return txHash.Hash().String(), mpcCommon.NewError(200), "", ""
}

func MintErc721(reqChain, contractAddr, caller, callerprivatekey, to, tokenid, uri string, addPrivilege bool) (string, mpcCommon.NftError, string, string) {
	tid, ok := big.NewInt(0).SetString(tokenid, 10)
	if !ok {
		txLog.LogE("Input token id [%v] not correct!", tokenid)
		return "", mpcCommon.NewError(403), "", ""
	}

	// get cfx client
	client, nftErr := client.GetCfxClient(reqChain)
	if !mpcCommon.Valid(nftErr) {
		txLog.LogE("Get cfx client failed! [%v]", nftErr.ErrorMsg)
		return "", nftErr, "", ""
	}

	accounts := client.AccountManager.List()
	fmt.Println("accounts-----------------11111:\n", accounts)

	for _, account := range accounts {
		client.AccountManager.Delete(account, txConf.PassWord)
		fmt.Println("delete account:", account)
	}

	address, err := txConf.AccountManager.ImportKey(callerprivatekey, txConf.PassWord)
	fmt.Println("1. import address: ", address)
	if err != nil {
		txLog.LogE("txConf Import to keystore failed! [%v]", err)
		// return "", mpcCommon.NewError(511)
	}
	// Import(keyFile, passphrase, newPassphrase string) (types.Address, error)

	// address, err = client.AccountManager.Import(txConf.KeystorePath, txConf.PassWord, txConf.PassWord)
	// fmt.Println("2. import address: ", address)
	// if err != nil {
	// 	txLog.LogE("client Import to keystore failed! [%v]", err)
	// 	// return "", mpcCommon.NewError(511)
	// }

	accounts = client.AccountManager.List()
	fmt.Println("accounts--------22222:\n", accounts)
	err = client.AccountManager.Unlock(address, txConf.PassWord)
	//err = client.AccountManager.UnlockDefault(txConf.PassWord)
	if err != nil {
		txLog.LogE("UnlockDefault failed! [%v]", err)
		return "", mpcCommon.NewError(511), "", ""
	}

	//get contract
	cfxContractAddr := cfxaddress.MustNew(contractAddr)

	instance, err := cfxerc721.NewCfxerc721(cfxContractAddr, client)
	if err != nil {
		txLog.LogE("NewCfxerc721 failed! [%v]", err)
		return "", mpcCommon.NewError(511), "", ""
	}

	cfxTo := cfxaddress.MustNew(to)
	tx, hash, err := instance.Mint(nil, cfxTo.MustGetCommonAddress(), tid, uri, addPrivilege)
	outTx := fmt.Sprintf("%v", tx)
	fmt.Println("outTx: ", outTx)
	if err != nil {
		txLog.LogE("Call contract Mint failed! [%v]", err)
		return "", mpcCommon.NewError(502), outTx, ""
	}

	// logrus.WithField("tx", tx).WithField("hash", hash).Info("MintErc721")
	receipt, err := client.WaitForTransationReceipt(*hash, time.Second)
	outRecipt := fmt.Sprintf("%v", receipt)
	fmt.Println("outRecipt: ", outRecipt)
	if err != nil {
		txLog.LogE("WaitForTransationReceipt failed! [%v]", err)
		return "", mpcCommon.NewError(514), outTx, outRecipt
	}
	// logrus.WithField("MintErc721 receipt", receipt).Info()

	return hash.String(), mpcCommon.NewError(200), outTx, outRecipt
}

func CfxMintErc1155(reqChain, contractAddr, caller, callerprivatekey, to, tokenid, tokenamount, uri string, addPrivilege bool) (string, mpcCommon.NftError, string, string) {
	tid, ok := big.NewInt(0).SetString(tokenid, 10)
	if !ok {
		txLog.LogE("Input token id [%v] not correct!", tokenid)
		return "", mpcCommon.NewError(403), "", ""
	}

	tamount, aerr := big.NewInt(0).SetString(tokenamount, 10)
	if !aerr {
		txLog.LogE("Input tammount [%v] not correct!", tokenamount)
		return "", mpcCommon.NewError(404), "", ""
	}
	fmt.Println("tammount:", tamount)

	// get cfx client
	client, nftErr := client.GetCfxClient(reqChain)
	if !mpcCommon.Valid(nftErr) {
		txLog.LogE("Get cfx client failed! [%v]", nftErr.ErrorMsg)
		return "", nftErr, "", ""
	}

	accounts := client.AccountManager.List()
	fmt.Println("accounts-----------------11111:\n", accounts)

	for _, account := range accounts {
		client.AccountManager.Delete(account, txConf.PassWord)
		fmt.Println("delete account:", account)
	}

	address, err := txConf.AccountManager.ImportKey(callerprivatekey, txConf.PassWord)
	fmt.Println("1. import address: ", address)
	if err != nil {
		txLog.LogE("txConf Import to keystore failed! [%v]", err)
		// return "", mpcCommon.NewError(511)
	}

	accounts = client.AccountManager.List()
	fmt.Println("accounts--------22222:\n", accounts)
	err = client.AccountManager.Unlock(address, txConf.PassWord)
	//err = client.AccountManager.UnlockDefault(txConf.PassWord)
	if err != nil {
		txLog.LogE("UnlockDefault failed! [%v]", err)
		return "", mpcCommon.NewError(511), "", ""
	}

	//get contract
	cfxContractAddr := cfxaddress.MustNew(contractAddr)

	instance, err := cfxerc1155.NewCfxerc1155(cfxContractAddr, client)
	if err != nil {
		txLog.LogE("NewCfxerc1155 failed! [%v]", err)
		return "", mpcCommon.NewError(511), "", ""
	}

	cfxTo := cfxaddress.MustNew(to)
	var tx *types.UnsignedTransaction
	var hash *types.Hash
	if tamount.Cmp(big.NewInt(1)) == 1 {
		tx, hash, err = instance.Mint(nil, cfxTo.MustGetCommonAddress(), tid, tamount, nil)
	} else {
		tx, hash, err = instance.Mint0(nil, cfxTo.MustGetCommonAddress(), tid, uri, addPrivilege, nil)
	}
	outTx := fmt.Sprintf("%v", tx)
	fmt.Println("outTx: ", outTx)
	if err != nil {
		txLog.LogE("Call 1155 contract Mint failed! [%v]", err)
		return "", mpcCommon.NewError(502), outTx, ""
	}

	// logrus.WithField("tx", tx).WithField("hash", hash).Info("CfxMintErc1155")
	receipt, err := client.WaitForTransationReceipt(*hash, time.Second)
	outRecipt := fmt.Sprintf("%v", receipt)
	fmt.Println("outRecipt: ", outRecipt)
	if err != nil {
		txLog.LogE("WaitForTransationReceipt failed! [%v]", err)
		return "", mpcCommon.NewError(514), outTx, outRecipt
	}

	// logrus.WithField("CfxMintErc1155 receipt", receipt).Info()

	return hash.String(), mpcCommon.NewError(200), outTx, outRecipt
}

func Burn(reqChain, contractAddr, caller, tokenid string) (string, mpcCommon.NftError, string, string) {
	tid, ok := big.NewInt(0).SetString(tokenid, 10)
	if !ok {
		txLog.LogE("Input token id [%v] not correct!", tokenid)
		return "", mpcCommon.NewError(403), "", ""
	}
	nftContract, opts, nftErr := getNftContractTransaction(reqChain, contractAddr, caller)
	if !mpcCommon.Valid(nftErr) {
		txLog.LogE("Get nft contract and transaction options failed! [%v]", nftErr.ErrorMsg)
		return "", nftErr, "", ""
	}
	tx, err := nftContract.Burn(opts, tid)
	if err != nil {
		txLog.LogE("Call contract Burn failed! [%v]", err)
		return "", mpcCommon.NewError(502), "", ""
	}
	return tx.Hash().String(), mpcCommon.NewError(200), "", ""
}

func BurnErc20(reqChain, contractAddr, caller, callerprivatekey, amount string) (string, mpcCommon.NftError, string, string) {
	tamount, ok := big.NewInt(0).SetString(amount, 10)
	if !ok {
		txLog.LogE("Input amount [%v] not correct!", amount)
		return "", mpcCommon.NewError(404), "", ""
	}

	// get cfx client
	client, nftErr := client.GetCfxClient(reqChain)
	if !mpcCommon.Valid(nftErr) {
		txLog.LogE("Get cfx client failed! [%v]", nftErr.ErrorMsg)
		return "", nftErr, "", ""
	}

	accounts := client.AccountManager.List()
	fmt.Println("accounts-----------------11111:\n", accounts)

	for _, account := range accounts {
		client.AccountManager.Delete(account, txConf.PassWord)
		fmt.Println("delete account:", account)
	}

	address, err := txConf.AccountManager.ImportKey(callerprivatekey, txConf.PassWord)
	fmt.Println("1. import address: ", address)
	if err != nil {
		txLog.LogE("txConf Import to keystore failed! [%v]", err)
		// return "", mpcCommon.NewError(511)
	}
	// Import(keyFile, passphrase, newPassphrase string) (types.Address, error)

	// address, err = client.AccountManager.Import(txConf.KeystorePath, txConf.PassWord, txConf.PassWord)
	// fmt.Println("2. import address: ", address)
	// if err != nil {
	// 	txLog.LogE("client Import to keystore failed! [%v]", err)
	// 	// return "", mpcCommon.NewError(511)
	// }

	accounts = client.AccountManager.List()
	fmt.Println("accounts--------22222:\n", accounts)
	err = client.AccountManager.Unlock(address, txConf.PassWord)
	//err = client.AccountManager.UnlockDefault(txConf.PassWord)
	if err != nil {
		txLog.LogE("UnlockDefault failed! [%v]", err)
		return "", mpcCommon.NewError(511), "", ""
	}

	//get contract
	cfxContractAddr := cfxaddress.MustNew(contractAddr)

	instance, err := cfxerc20.NewCfxerc20(cfxContractAddr, client)
	if err != nil {
		txLog.LogE("NewCfxerc20 failed! [%v]", err)
		return "", mpcCommon.NewError(511), "", ""
	}

	tx, hash, err := instance.Burn(nil, tamount)
	outTx := fmt.Sprintf("%v", tx)
	fmt.Println("outTx: ", outTx)
	if err != nil {
		txLog.LogE("Call contract Mint failed! [%v]", err)
		return "", mpcCommon.NewError(502), outTx, ""
	}

	// logrus.WithField("tx", tx).WithField("hash", hash).Info("BurnErc20")
	receipt, err := client.WaitForTransationReceipt(*hash, time.Second)
	outRecipt := fmt.Sprintf("%v", receipt)
	fmt.Println("outRecipt: ", outRecipt)
	if err != nil {
		txLog.LogE("WaitForTransationReceipt failed! [%v]", err)
		return "", mpcCommon.NewError(514), outTx, outRecipt
	}
	// logrus.WithField("BurnErc20 receipt", receipt).Info()

	return hash.String(), mpcCommon.NewError(200), outTx, outRecipt
}

func BurnErc721(reqChain, contractAddr, caller, callerprivatekey, tokenid string) (string, mpcCommon.NftError, string, string) {
	tid, ok := big.NewInt(0).SetString(tokenid, 10)
	if !ok {
		txLog.LogE("Input token id [%v] not correct!", tokenid)
		return "", mpcCommon.NewError(403), "", ""
	}
	// get cfx client
	client, nftErr := client.GetCfxClient(reqChain)
	if !mpcCommon.Valid(nftErr) {
		txLog.LogE("Get cfx client failed! [%v]", nftErr.ErrorMsg)
		return "", nftErr, "", ""
	}

	accounts := client.AccountManager.List()
	fmt.Println("accounts-----------------11111:\n", accounts)

	for _, account := range accounts {
		client.AccountManager.Delete(account, txConf.PassWord)
		fmt.Println("delete account:", account)
	}

	address, err := txConf.AccountManager.ImportKey(callerprivatekey, txConf.PassWord)
	fmt.Println("1. import address: ", address)
	if err != nil {
		txLog.LogE("txConf Import to keystore failed! [%v]", err)
		// return "", mpcCommon.NewError(511)
	}
	// Import(keyFile, passphrase, newPassphrase string) (types.Address, error)

	// address, err = client.AccountManager.Import(txConf.KeystorePath, txConf.PassWord, txConf.PassWord)
	// fmt.Println("2. import address: ", address)
	// if err != nil {
	// 	txLog.LogE("client Import to keystore failed! [%v]", err)
	// 	// return "", mpcCommon.NewError(511)
	// }

	accounts = client.AccountManager.List()
	fmt.Println("accounts--------22222:\n", accounts)
	err = client.AccountManager.Unlock(address, txConf.PassWord)
	//err = client.AccountManager.UnlockDefault(txConf.PassWord)
	if err != nil {
		txLog.LogE("UnlockDefault failed! [%v]", err)
		return "", mpcCommon.NewError(511), "", ""
	}

	//get contract
	cfxContractAddr := cfxaddress.MustNew(contractAddr)

	instance, err := cfxerc721.NewCfxerc721(cfxContractAddr, client)
	if err != nil {
		txLog.LogE("NewCfxerc721 failed! [%v]", err)
		return "", mpcCommon.NewError(511), "", ""
	}

	tx, hash, err := instance.Burn(nil, tid)
	outTx := fmt.Sprintf("%v", tx)
	fmt.Println("outTx: ", outTx)
	if err != nil {
		txLog.LogE("Call contract Mint failed! [%v]", err)
		return "", mpcCommon.NewError(502), outTx, ""
	}

	// logrus.WithField("tx", tx).WithField("hash", hash).Info("CfxBurnEr721")
	receipt, err := client.WaitForTransationReceipt(*hash, time.Second)
	outRecipt := fmt.Sprintf("%v", receipt)
	fmt.Println("outRecipt: ", outRecipt)
	if err != nil {
		txLog.LogE("WaitForTransationReceipt failed! [%v]", err)
		return "", mpcCommon.NewError(514), outTx, outRecipt
	}
	// logrus.WithField("CfxBurnEr721 receipt", receipt).Info()

	return hash.String(), mpcCommon.NewError(200), outTx, outRecipt
}

func BurnErc1155(reqChain, contractAddr, caller, callerprivatekey, _account, tokenid, amount string) (string, mpcCommon.NftError, string, string) {
	tid, ok := big.NewInt(0).SetString(tokenid, 10)
	if !ok {
		txLog.LogE("Input token id [%v] not correct!", tokenid)
		return "", mpcCommon.NewError(403), "", ""
	}
	tamount, ok := big.NewInt(0).SetString(amount, 10)
	if !ok {
		txLog.LogE("Input amount [%v] not correct!", amount)
		return "", mpcCommon.NewError(404), "", ""
	}
	// get cfx client
	client, nftErr := client.GetCfxClient(reqChain)
	if !mpcCommon.Valid(nftErr) {
		txLog.LogE("Get cfx client failed! [%v]", nftErr.ErrorMsg)
		return "", nftErr, "", ""
	}

	accounts := client.AccountManager.List()
	fmt.Println("accounts-----------------11111:\n", accounts)

	for _, account := range accounts {
		client.AccountManager.Delete(account, txConf.PassWord)
		fmt.Println("delete account:", account)
	}

	address, err := txConf.AccountManager.ImportKey(callerprivatekey, txConf.PassWord)
	fmt.Println("1. import address: ", address)
	if err != nil {
		txLog.LogE("txConf Import to keystore failed! [%v]", err)
		// return "", mpcCommon.NewError(511)
	}
	// Import(keyFile, passphrase, newPassphrase string) (types.Address, error)

	// address, err = client.AccountManager.Import(txConf.KeystorePath, txConf.PassWord, txConf.PassWord)
	// fmt.Println("2. import address: ", address)
	// if err != nil {
	// 	txLog.LogE("client Import to keystore failed! [%v]", err)
	// 	// return "", mpcCommon.NewError(511)
	// }

	accounts = client.AccountManager.List()
	fmt.Println("accounts--------22222:\n", accounts)
	err = client.AccountManager.Unlock(address, txConf.PassWord)
	//err = client.AccountManager.UnlockDefault(txConf.PassWord)
	if err != nil {
		txLog.LogE("UnlockDefault failed! [%v]", err)
		return "", mpcCommon.NewError(511), "", ""
	}

	//get contract
	cfxContractAddr := cfxaddress.MustNew(contractAddr)

	instance, err := cfxerc1155.NewCfxerc1155(cfxContractAddr, client)
	if err != nil {
		txLog.LogE("NewCfxerc1155 failed! [%v]", err)
		return "", mpcCommon.NewError(511), "", ""
	}

	cfxAccount := cfxaddress.MustNew(_account)
	fmt.Println("----------------------From: ", cfxAccount)

	tx, hash, err := instance.Burn(nil, cfxAccount.MustGetCommonAddress(), tid, tamount)
	outTx := fmt.Sprintf("%v", tx)
	fmt.Println("outTx: ", outTx)
	if err != nil {
		txLog.LogE("Call contract Burn failed! [%v]", err)
		return "", mpcCommon.NewError(502), outTx, ""
	}

	// logrus.WithField("tx", tx).WithField("hash", hash).Info("BurnErc1155")
	receipt, err := client.WaitForTransationReceipt(*hash, time.Second)
	outRecipt := fmt.Sprintf("%v", receipt)
	fmt.Println("outRecipt: ", outRecipt)
	if err != nil {
		txLog.LogE("WaitForTransationReceipt failed! [%v]", err)
		return "", mpcCommon.NewError(514), outTx, outRecipt
	}
	// logrus.WithField("BurnErc1155 receipt", receipt).Info()

	return hash.String(), mpcCommon.NewError(200), outTx, outRecipt
}

// TODO:
func CfxBurnBatchErc1155(reqChain, contractAddr, caller, callerprivatekey, _account, tokenid, amount string) (string, mpcCommon.NftError, string, string) {
	tid, ok := big.NewInt(0).SetString(tokenid, 10)
	if !ok {
		txLog.LogE("Input token id [%v] not correct!", tokenid)
		return "", mpcCommon.NewError(403), "", ""
	}
	tamount, ok := big.NewInt(0).SetString(amount, 10)
	if !ok {
		txLog.LogE("Input amount [%v] not correct!", amount)
		return "", mpcCommon.NewError(404), "", ""
	}
	// get cfx client
	client, nftErr := client.GetCfxClient(reqChain)
	if !mpcCommon.Valid(nftErr) {
		txLog.LogE("Get cfx client failed! [%v]", nftErr.ErrorMsg)
		return "", nftErr, "", ""
	}

	accounts := client.AccountManager.List()
	fmt.Println("accounts-----------------11111:\n", accounts)

	for _, account := range accounts {
		client.AccountManager.Delete(account, txConf.PassWord)
		fmt.Println("delete account:", account)
	}

	address, err := txConf.AccountManager.ImportKey(callerprivatekey, txConf.PassWord)
	fmt.Println("1. import address: ", address)
	if err != nil {
		txLog.LogE("txConf Import to keystore failed! [%v]", err)
		// return "", mpcCommon.NewError(511)
	}
	// Import(keyFile, passphrase, newPassphrase string) (types.Address, error)

	// address, err = client.AccountManager.Import(txConf.KeystorePath, txConf.PassWord, txConf.PassWord)
	// fmt.Println("2. import address: ", address)
	// if err != nil {
	// 	txLog.LogE("client Import to keystore failed! [%v]", err)
	// 	// return "", mpcCommon.NewError(511)
	// }

	accounts = client.AccountManager.List()
	fmt.Println("accounts--------22222:\n", accounts)
	err = client.AccountManager.Unlock(address, txConf.PassWord)
	//err = client.AccountManager.UnlockDefault(txConf.PassWord)
	if err != nil {
		txLog.LogE("UnlockDefault failed! [%v]", err)
		return "", mpcCommon.NewError(511), "", ""
	}

	//get contract
	cfxContractAddr := cfxaddress.MustNew(contractAddr)

	instance, err := cfxerc1155.NewCfxerc1155(cfxContractAddr, client)
	if err != nil {
		txLog.LogE("NewCfxerc1155 failed! [%v]", err)
		return "", mpcCommon.NewError(511), "", ""
	}

	cfxAccount := cfxaddress.MustNew(_account)
	fmt.Println("----------------------From: ", cfxAccount)

	tx, hash, err := instance.Burn(nil, cfxAccount.MustGetCommonAddress(), tid, tamount)
	outTx := fmt.Sprintf("%v", tx)
	fmt.Println("outTx: ", outTx)
	if err != nil {
		txLog.LogE("Call contract Burn failed! [%v]", err)
		return "", mpcCommon.NewError(502), outTx, ""
	}

	// logrus.WithField("tx", tx).WithField("hash", hash).Info("BurnErc1155")
	receipt, err := client.WaitForTransationReceipt(*hash, time.Second)
	outRecipt := fmt.Sprintf("%v", receipt)
	fmt.Println("outRecipt: ", outRecipt)
	if err != nil {
		txLog.LogE("WaitForTransationReceipt failed! [%v]", err)
		return "", mpcCommon.NewError(514), outTx, outRecipt
	}
	// logrus.WithField("BurnErc1155 receipt", receipt).Info()

	return hash.String(), mpcCommon.NewError(200), outTx, outRecipt
}

func TransferCFX(reqChain, caller, callprivatekey, to, amount string) (string, mpcCommon.NftError, string, string) {
	tamount, ok := big.NewInt(0).SetString(amount, 10)
	if !ok {
		txLog.LogE("Input amount [%v] not correct!", amount)
		return "", mpcCommon.NewError(403), "", ""
	}

	// get cfx client
	client, nftErr := client.GetCfxClient(reqChain)
	if !mpcCommon.Valid(nftErr) {
		txLog.LogE("Get cfx client failed! [%v]", nftErr.ErrorMsg)
		return "", nftErr, "", ""
	}

	accounts := client.AccountManager.List()
	fmt.Println("accounts-----------------11111:\n", accounts)

	for _, account := range accounts {
		client.AccountManager.Delete(account, txConf.PassWord)
		fmt.Println("delete account:", account)
	}

	// address, err := account.CfxImportAccount(callprivatekey)
	address, err := txConf.AccountManager.ImportKey(callprivatekey, txConf.PassWord)
	fmt.Println("import address: ", address)
	if err != nil {
		txLog.LogE("Cfx Import to keystore failed! [%v]", err)
		// return "", mpcCommon.NewError(511)
	}
	accounts = client.AccountManager.List()
	fmt.Println("accounts--------22222:\n", accounts)
	// err = client.AccountManager.Unlock(cfxFrom, txConf.PassWord)
	err = client.AccountManager.UnlockDefault(txConf.PassWord)
	if err != nil {
		txLog.LogE("Unlock failed! [%v]", err)
		return "", mpcCommon.NewError(511), "", ""
	}

	// accounts := client.AccountManager.List()
	// fmt.Println("accounts:\n", accounts)

	// err := client.AccountManager.UnlockDefault(txConf.PassWord)
	// if err != nil {
	// 	txLog.LogE("UnlockDefault failed! [%v]", err)
	// 	return "", mpcCommon.NewError(511)
	// }

	cfxFrom := cfxaddress.MustNew(caller)
	fmt.Println("-------------------------------From: ", cfxFrom)

	cfxTo := cfxaddress.MustNew(to)
	fmt.Println("-------------------------------To: ", cfxTo)

	utx, _ := client.CreateUnsignedTransaction(cfxFrom, cfxTo, types.NewBigIntByRaw(tamount), nil)
	hash, err := client.SendTransaction(utx)

	outTx := fmt.Sprintf("%v", utx)
	// logrus.WithField("tx", tx).WithField("hash", hash).Info("TransferFromERC20")
	receipt, err := client.WaitForTransationReceipt(hash, time.Second)
	outRecipt := fmt.Sprintf("%v", receipt)
	fmt.Println("outRecipt: ", outRecipt)
	if err != nil {
		txLog.LogE("WaitForTransationReceipt failed! [%v]", err)
		return "", mpcCommon.NewError(514), outTx, outRecipt
	}

	// logrus.WithField("TransferFromERC20 receipt", receipt).Info()

	return hash.String(), mpcCommon.NewError(200), outTx, outRecipt
}

func TransferFromERC20(reqChain, contractAddr, caller, callprivatekey, to, amount string, addPrivilege bool) (string, mpcCommon.NftError, string, string) {
	tamount, ok := big.NewInt(0).SetString(amount, 10)
	if !ok {
		txLog.LogE("Input amount [%v] not correct!", amount)
		return "", mpcCommon.NewError(403), "", ""
	}

	// get cfx client
	client, nftErr := client.GetCfxClient(reqChain)
	if !mpcCommon.Valid(nftErr) {
		txLog.LogE("Get cfx client failed! [%v]", nftErr.ErrorMsg)
		return "", nftErr, "", ""
	}

	accounts := client.AccountManager.List()
	fmt.Println("accounts-----------------11111:\n", accounts)

	for _, account := range accounts {
		client.AccountManager.Delete(account, txConf.PassWord)
		fmt.Println("delete account:", account)
	}

	// address, err := account.CfxImportAccount(callprivatekey)
	address, err := txConf.AccountManager.ImportKey(callprivatekey, txConf.PassWord)
	fmt.Println("import address: ", address)
	if err != nil {
		txLog.LogE("Cfx Import to keystore failed! [%v]", err)
		// return "", mpcCommon.NewError(511)
	}
	accounts = client.AccountManager.List()
	fmt.Println("accounts--------22222:\n", accounts)
	// err = client.AccountManager.Unlock(cfxFrom, txConf.PassWord)
	err = client.AccountManager.UnlockDefault(txConf.PassWord)
	if err != nil {
		txLog.LogE("Unlock failed! [%v]", err)
		return "", mpcCommon.NewError(511), "", ""
	}

	// accounts := client.AccountManager.List()
	// fmt.Println("accounts:\n", accounts)

	// err := client.AccountManager.UnlockDefault(txConf.PassWord)
	// if err != nil {
	// 	txLog.LogE("UnlockDefault failed! [%v]", err)
	// 	return "", mpcCommon.NewError(511)
	// }

	//get contract
	cfxContractAddr := cfxaddress.MustNew(contractAddr)
	instance, err := cfxerc20.NewCfxerc20(cfxContractAddr, client)
	if err != nil {
		txLog.LogE("NewCfxerc20 failed! [%v]", err)
		return "", mpcCommon.NewError(512), "", ""
	}

	cfxTo := cfxaddress.MustNew(to)
	fmt.Println("-------------------------------To: ", cfxTo)
	tx, hash, err := instance.Transfer0(nil, cfxTo.MustGetCommonAddress(), tamount, addPrivilege)
	outTx := fmt.Sprintf("%v", tx)
	fmt.Println("outTx: ", outTx)
	if err != nil {
		txLog.LogE("Call contract SafeTransferFrom failed! [%v]", err)
		return "", mpcCommon.NewError(502), outTx, ""
	}

	// logrus.WithField("tx", tx).WithField("hash", hash).Info("TransferFromERC20")
	receipt, err := client.WaitForTransationReceipt(*hash, time.Second)
	outRecipt := fmt.Sprintf("%v", receipt)
	fmt.Println("outRecipt: ", outRecipt)
	if err != nil {
		txLog.LogE("WaitForTransationReceipt failed! [%v]", err)
		return "", mpcCommon.NewError(514), outTx, outRecipt
	}

	// logrus.WithField("TransferFromERC20 receipt", receipt).Info()

	return hash.String(), mpcCommon.NewError(200), outTx, outRecipt
}

func SafeTransferFromERC721(reqChain, contractAddr, caller, callprivatekey, from, to, tokenid string, addPrivilege bool) (string, mpcCommon.NftError, string, string) {

	tid, ok := big.NewInt(0).SetString(tokenid, 10)
	if !ok {
		txLog.LogE("Input token id [%v] not correct!", tokenid)
		return "", mpcCommon.NewError(403), "", ""
	}

	// get cfx client
	client, nftErr := client.GetCfxClient(reqChain)
	if !mpcCommon.Valid(nftErr) {
		txLog.LogE("Get cfx client failed! [%v]", nftErr.ErrorMsg)
		return "", nftErr, "", ""
	}

	accounts := client.AccountManager.List()
	fmt.Println("accounts-----------------11111:\n", accounts)

	for _, account := range accounts {
		client.AccountManager.Delete(account, txConf.PassWord)
		fmt.Println("delete account:", account)
	}

	// address, err := account.CfxImportAccount(callprivatekey)
	address, err := txConf.AccountManager.ImportKey(callprivatekey, txConf.PassWord)
	fmt.Println("import address: ", address)
	if err != nil {
		txLog.LogE("Cfx Import to keystore failed! [%v]", err)
		// return "", mpcCommon.NewError(511)
	}
	cfxFrom := cfxaddress.MustNew(from)
	fmt.Println("----------------------From: ", cfxFrom)

	accounts = client.AccountManager.List()
	fmt.Println("accounts--------22222:\n", accounts)
	// err = client.AccountManager.Unlock(cfxFrom, txConf.PassWord)
	err = client.AccountManager.UnlockDefault(txConf.PassWord)
	if err != nil {
		txLog.LogE("Unlock failed! [%v]", err)
		return "", mpcCommon.NewError(511), "", ""
	}

	// accounts := client.AccountManager.List()
	// fmt.Println("accounts:\n", accounts)

	// err := client.AccountManager.UnlockDefault(txConf.PassWord)
	// if err != nil {
	// 	txLog.LogE("UnlockDefault failed! [%v]", err)
	// 	return "", mpcCommon.NewError(511)
	// }

	//get contract
	cfxContractAddr := cfxaddress.MustNew(contractAddr)
	instance, err := cfxerc721.NewCfxerc721(cfxContractAddr, client)
	if err != nil {
		txLog.LogE("NewCfxerc721 failed! [%v]", err)
		return "", mpcCommon.NewError(512), "", ""
	}

	cfxTo := cfxaddress.MustNew(to)
	fmt.Println("-------------------------------To: ", cfxTo)
	tx, hash, err := instance.SafeTransferFrom1(nil, cfxFrom.MustGetCommonAddress(), cfxTo.MustGetCommonAddress(), tid, addPrivilege)
	outTx := fmt.Sprintf("%v", tx)
	fmt.Println("outTx: ", outTx)
	if err != nil {
		txLog.LogE("Call contract SafeTransferFrom1! [%v]", err)
		return "", mpcCommon.NewError(502), outTx, ""
	}

	// logrus.WithField("tx", tx).WithField("hash", hash).Info("SafeTransferFrom1)
	receipt, err := client.WaitForTransationReceipt(*hash, time.Second)
	outRecipt := fmt.Sprintf("%v", receipt)
	fmt.Println("outRecipt: ", outRecipt)
	if err != nil {
		txLog.LogE("WaitForTransationReceipt failed! [%v]", err)
		return "", mpcCommon.NewError(514), outTx, outRecipt
	}

	// logrus.WithField("SafeTransferFromERC721 receipt", receipt).Info()

	return hash.String(), mpcCommon.NewError(200), outTx, outRecipt
}

func SafeTransferFromERC1155(reqChain, contractAddr, caller, callprivatekey, from, to, tokenid, tokenamount string, addPrivilege bool, data []byte) (string, mpcCommon.NftError, string, string) {

	tid, ok := big.NewInt(0).SetString(tokenid, 10)
	if !ok {
		txLog.LogE("Input token id [%v] not correct!", tokenid)
		return "", mpcCommon.NewError(403), "", ""
	}

	tammount, ok := big.NewInt(0).SetString(tokenamount, 10)
	if !ok {
		txLog.LogE("Input tokenamount [%v] not correct!", tokenamount)
		return "", mpcCommon.NewError(404), "", ""
	}

	// get cfx client
	client, nftErr := client.GetCfxClient(reqChain)
	if !mpcCommon.Valid(nftErr) {
		txLog.LogE("Get cfx client failed! [%v]", nftErr.ErrorMsg)
		return "", nftErr, "", ""
	}

	accounts := client.AccountManager.List()
	fmt.Println("accounts-----------------11111:\n", accounts)

	for _, account := range accounts {
		client.AccountManager.Delete(account, txConf.PassWord)
		fmt.Println("delete account:", account)
	}

	// address, err := account.CfxImportAccount(callprivatekey)
	address, err := txConf.AccountManager.ImportKey(callprivatekey, txConf.PassWord)
	fmt.Println("import address: ", address)
	if err != nil {
		txLog.LogE("Cfx Import to keystore failed! [%v]", err)
		// return "", mpcCommon.NewError(511)
	}
	cfxFrom := cfxaddress.MustNew(from)
	fmt.Println("----------------------cfxFrom: ", cfxFrom)

	accounts = client.AccountManager.List()
	fmt.Println("accounts--------22222:\n", accounts)
	// err = client.AccountManager.Unlock(cfxFrom, txConf.PassWord)
	err = client.AccountManager.UnlockDefault(txConf.PassWord)
	if err != nil {
		txLog.LogE("Unlock failed! [%v]", err)
		return "", mpcCommon.NewError(511), "", ""
	}

	//get contract
	cfxContractAddr := cfxaddress.MustNew(contractAddr)
	instance, err := cfxerc1155.NewCfxerc1155(cfxContractAddr, client)
	if err != nil {
		txLog.LogE("NewCfxerc1155 failed! [%v]", err)
		return "", mpcCommon.NewError(512), "", ""
	}

	fmt.Println("--------------------------to: ", to)
	cfxTo := cfxaddress.MustNew(to)
	tx, hash, err := instance.SafeTransferFrom(nil, cfxFrom.MustGetCommonAddress(), cfxTo.MustGetCommonAddress(), tid, tammount, addPrivilege, nil)
	outTx := fmt.Sprintf("%v", tx)
	fmt.Println("outTx: ", outTx)
	fmt.Println("hash: ", hash)
	if err != nil {
		txLog.LogE("Call contract SafeTransferFrom failed! [%v]", err)
		return "", mpcCommon.NewError(502), outTx, ""
	}

	// logrus.WithField("tx", tx).WithField("hash", hash).Info("SafeTransferFromERC1155")
	receipt, err := client.WaitForTransationReceipt(*hash, time.Second)
	outRecipt := fmt.Sprintf("%v", receipt)
	fmt.Println("outRecipt: ", outRecipt)
	if err != nil {
		txLog.LogE("WaitForTransationReceipt failed! [%v]", err)
		return "", mpcCommon.NewError(514), outTx, outRecipt
	}
	// logrus.WithField("SafeTransferFromERC1155 receipt", receipt).Info()

	return hash.String(), mpcCommon.NewError(200), outTx, outRecipt
}

func SafeTransferFrom(reqChain, contractAddr, caller, from, to, tokenid string) (string, mpcCommon.NftError, string, string) {
	tid, ok := big.NewInt(0).SetString(tokenid, 10)
	if !ok {
		txLog.LogE("Input token id [%v] not correct!", tokenid)
		return "", mpcCommon.NewError(403), "", ""
	}
	nftContract, opts, nftErr := getNftContractTransaction(reqChain, contractAddr, caller)
	if !mpcCommon.Valid(nftErr) {
		txLog.LogE("Get nft contract and transaction options failed! [%v]", nftErr.ErrorMsg)
		return "", nftErr, "", ""
	}
	tx, err := nftContract.SafeTransferFrom(opts, common.HexToAddress(from), common.HexToAddress(to), tid)
	if err != nil {
		txLog.LogE("Call contract SafeTransferFrom failed! [%v]", err)
		return "", mpcCommon.NewError(502), "", ""
	}
	return tx.Hash().String(), mpcCommon.NewError(200), "", ""
}

func SafeTransferFromWithDataERC721(reqChain, contractAddr, caller, callprivatekey, from, to, tokenid string, addPrivilege bool, data []byte) (string, mpcCommon.NftError, string, string) {
	tid, ok := big.NewInt(0).SetString(tokenid, 10)
	if !ok {
		txLog.LogE("Input token id [%v] not correct!", tokenid)
		return "", mpcCommon.NewError(403), "", ""
	}
	nftContract, opts, nftErr := getNftContractTransaction(reqChain, contractAddr, caller)
	if !mpcCommon.Valid(nftErr) {
		txLog.LogE("Get nft contract and transaction options failed! [%v]", nftErr.ErrorMsg)
		return "", nftErr, "", ""
	}
	tx, err := nftContract.SafeTransferFrom0(opts, common.HexToAddress(from), common.HexToAddress(to), tid, data)
	if err != nil {
		txLog.LogE("Call contract SafeTransferFrom0 failed! [%v]", err)
		return "", mpcCommon.NewError(502), "", ""
	}
	return tx.Hash().String(), mpcCommon.NewError(200), "", ""
}

func SafeTransferFromWithData(reqChain, contractAddr, caller, from, to, tokenid string, data []byte) (string, mpcCommon.NftError, string, string) {
	tid, ok := big.NewInt(0).SetString(tokenid, 10)
	if !ok {
		txLog.LogE("Input token id [%v] not correct!", tokenid)
		return "", mpcCommon.NewError(403), "", ""
	}
	nftContract, opts, nftErr := getNftContractTransaction(reqChain, contractAddr, caller)
	if !mpcCommon.Valid(nftErr) {
		txLog.LogE("Get nft contract and transaction options failed! [%v]", nftErr.ErrorMsg)
		return "", nftErr, "", ""
	}
	tx, err := nftContract.SafeTransferFrom0(opts, common.HexToAddress(from), common.HexToAddress(to), tid, data)
	if err != nil {
		txLog.LogE("Call contract SafeTransferFrom0 failed! [%v]", err)
		return "", mpcCommon.NewError(502), "", ""
	}
	return tx.Hash().String(), mpcCommon.NewError(200), "", ""
}

func TransferFrom(reqChain, contractAddr, caller, from, to, tokenid string) (string, mpcCommon.NftError, string, string) {
	tid, ok := big.NewInt(0).SetString(tokenid, 10)
	if !ok {
		txLog.LogE("Input token id [%v] not correct!", tokenid)
		return "", mpcCommon.NewError(403), "", ""
	}
	nftContract, opts, nftErr := getNftContractTransaction(reqChain, contractAddr, caller)
	if !mpcCommon.Valid(nftErr) {
		txLog.LogE("Get nft contract and transaction options failed! [%v]", nftErr.ErrorMsg)
		return "", nftErr, "", ""
	}
	tx, err := nftContract.TransferFrom(opts, common.HexToAddress(from), common.HexToAddress(to), tid)
	if err != nil {
		txLog.LogE("Call contract TransferFrom failed! [%v]", err)
		return "", mpcCommon.NewError(502), "", ""
	}
	return tx.Hash().String(), mpcCommon.NewError(200), "", ""
}

func ApproveERC20(reqChain, contractAddr, caller, callprivatekey, approvedOperator, tokenamount string) (string, mpcCommon.NftError, string, string) {

	ttokenamount, ok := big.NewInt(0).SetString(tokenamount, 10)
	if !ok {
		txLog.LogE("Input token amount [%v] not correct!", tokenamount)
		return "", mpcCommon.NewError(404), "", ""
	}

	// get cfx client
	client, nftErr := client.GetCfxClient(reqChain)
	if !mpcCommon.Valid(nftErr) {
		txLog.LogE("Get cfx client failed! [%v]", nftErr.ErrorMsg)
		return "", nftErr, "", ""
	}

	accounts := client.AccountManager.List()
	fmt.Println("accounts-----------------11111:\n", accounts)

	for _, account := range accounts {
		client.AccountManager.Delete(account, txConf.PassWord)
		fmt.Println("delete account:", account)
	}

	address, err := txConf.AccountManager.ImportKey(callprivatekey, txConf.PassWord)
	fmt.Println("import address: ", address)
	if err != nil {
		txLog.LogE("Cfx Import to keystore failed! [%v]", err)
		// return "", mpcCommon.NewError(511)
	}
	cfxApprovedOperator := cfxaddress.MustNew(approvedOperator)
	fmt.Println("----------------------From: ", cfxApprovedOperator)

	accounts = client.AccountManager.List()
	fmt.Println("accounts--------22222:\n", accounts)
	err = client.AccountManager.UnlockDefault(txConf.PassWord)
	if err != nil {
		txLog.LogE("Unlock failed! [%v]", err)
		return "", mpcCommon.NewError(511), "", ""
	}

	// accounts := client.AccountManager.List()
	// fmt.Println("accounts:\n", accounts)

	// err := client.AccountManager.UnlockDefault(txConf.PassWord)
	// if err != nil {
	// 	txLog.LogE("UnlockDefault failed! [%v]", err)
	// 	return "", mpcCommon.NewError(511)
	// }

	//get contract
	cfxContractAddr := cfxaddress.MustNew(contractAddr)
	instance, err := cfxerc20.NewCfxerc20(cfxContractAddr, client)
	if err != nil {
		txLog.LogE("NewCfxerc20 failed! [%v]", err)
		return "", mpcCommon.NewError(512), "", ""
	}

	tx, hash, err := instance.Approve(nil, cfxApprovedOperator.MustGetCommonAddress(), ttokenamount)
	outTx := fmt.Sprintf("%v", tx)
	fmt.Println("outTx: ", outTx)
	if err != nil {
		txLog.LogE("Call contract Approve failed! [%v]", err)
		return "", mpcCommon.NewError(502), outTx, ""
	}

	// logrus.WithField("tx", tx).WithField("hash", hash).Info("ApproveERC721")
	receipt, err := client.WaitForTransationReceipt(*hash, time.Second)
	outRecipt := fmt.Sprintf("%v", receipt)
	fmt.Println("outRecipt: ", outRecipt)
	if err != nil {
		txLog.LogE("WaitForTransationReceipt failed! [%v]", err)
		return "", mpcCommon.NewError(514), outTx, outRecipt
	}

	// logrus.WithField("ApproveERC721 receipt", receipt).Info()

	return hash.String(), mpcCommon.NewError(200), outTx, outRecipt
}

func ApproveERC721(reqChain, contractAddr, caller, callprivatekey, approvedOperator, tokenid string) (string, mpcCommon.NftError, string, string) {

	tid, ok := big.NewInt(0).SetString(tokenid, 10)
	if !ok {
		txLog.LogE("Input token id [%v] not correct!", tokenid)
		return "", mpcCommon.NewError(403), "", ""
	}

	// get cfx client
	client, nftErr := client.GetCfxClient(reqChain)
	if !mpcCommon.Valid(nftErr) {
		txLog.LogE("Get cfx client failed! [%v]", nftErr.ErrorMsg)
		return "", nftErr, "", ""
	}

	accounts := client.AccountManager.List()
	fmt.Println("accounts-----------------11111:\n", accounts)

	for _, account := range accounts {
		client.AccountManager.Delete(account, txConf.PassWord)
		fmt.Println("delete account:", account)
	}

	address, err := txConf.AccountManager.ImportKey(callprivatekey, txConf.PassWord)
	fmt.Println("import address: ", address)
	if err != nil {
		txLog.LogE("Cfx Import to keystore failed! [%v]", err)
		// return "", mpcCommon.NewError(511)
	}
	cfxApprovedOperator := cfxaddress.MustNew(approvedOperator)
	fmt.Println("----------------------From: ", cfxApprovedOperator)

	accounts = client.AccountManager.List()
	fmt.Println("accounts--------22222:\n", accounts)
	err = client.AccountManager.UnlockDefault(txConf.PassWord)
	if err != nil {
		txLog.LogE("Unlock failed! [%v]", err)
		return "", mpcCommon.NewError(511), "", ""
	}

	// accounts := client.AccountManager.List()
	// fmt.Println("accounts:\n", accounts)

	// err := client.AccountManager.UnlockDefault(txConf.PassWord)
	// if err != nil {
	// 	txLog.LogE("UnlockDefault failed! [%v]", err)
	// 	return "", mpcCommon.NewError(511)
	// }

	//get contract
	cfxContractAddr := cfxaddress.MustNew(contractAddr)
	instance, err := cfxerc721.NewCfxerc721(cfxContractAddr, client)
	if err != nil {
		txLog.LogE("NewCfxerc721 failed! [%v]", err)
		return "", mpcCommon.NewError(512), "", ""
	}

	tx, hash, err := instance.Approve(nil, cfxApprovedOperator.MustGetCommonAddress(), tid)
	outTx := fmt.Sprintf("%v", tx)
	fmt.Println("outTx: ", outTx)
	if err != nil {
		txLog.LogE("Call contract Approve failed! [%v]", err)
		return "", mpcCommon.NewError(502), outTx, ""
	}

	// logrus.WithField("tx", tx).WithField("hash", hash).Info("ApproveERC721")
	receipt, err := client.WaitForTransationReceipt(*hash, time.Second)
	outRecipt := fmt.Sprintf("%v", receipt)
	fmt.Println("outRecipt: ", outRecipt)
	if err != nil {
		txLog.LogE("WaitForTransationReceipt failed! [%v]", err)
		return "", mpcCommon.NewError(514), outTx, outRecipt
	}

	// logrus.WithField("ApproveERC721 receipt", receipt).Info()

	return hash.String(), mpcCommon.NewError(200), outTx, outRecipt
}

func Approve(reqChain, contractAddr, caller, approved, tokenid string) (string, mpcCommon.NftError, string, string) {
	tid, ok := big.NewInt(0).SetString(tokenid, 10)
	if !ok {
		txLog.LogE("Input token id [%v] not correct!", tokenid)
		return "", mpcCommon.NewError(403), "", ""
	}
	nftContract, opts, nftErr := getNftContractTransaction(reqChain, contractAddr, caller)
	if !mpcCommon.Valid(nftErr) {
		txLog.LogE("Get nft contract and transaction options failed! [%v]", nftErr.ErrorMsg)
		return "", nftErr, "", ""
	}
	tx, err := nftContract.Approve(opts, common.HexToAddress(approved), tid)
	if err != nil {
		txLog.LogE("Call contract Approve failed! [%v]", err)
		return "", mpcCommon.NewError(502), "", ""
	}
	return tx.Hash().String(), mpcCommon.NewError(200), "", ""
}

func SetApproveForAllERC1155(reqChain, contractAddr, caller, callprivatekey, approvedOperator string, flag bool) (string, mpcCommon.NftError, string, string) {

	// get cfx client
	client, nftErr := client.GetCfxClient(reqChain)
	if !mpcCommon.Valid(nftErr) {
		txLog.LogE("Get cfx client failed! [%v]", nftErr.ErrorMsg)
		return "", nftErr, "", ""
	}

	accounts := client.AccountManager.List()
	fmt.Println("accounts-----------------11111:\n", accounts)

	for _, account := range accounts {
		client.AccountManager.Delete(account, txConf.PassWord)
		fmt.Println("delete account:", account)
	}

	address, err := txConf.AccountManager.ImportKey(callprivatekey, txConf.PassWord)
	fmt.Println("import address: ", address)
	if err != nil {
		txLog.LogE("Cfx Import to keystore failed! [%v]", err)
		// return "", mpcCommon.NewError(511)
	}
	cfxApprovedOperator := cfxaddress.MustNew(approvedOperator)
	fmt.Println("----------------------From: ", cfxApprovedOperator)

	accounts = client.AccountManager.List()
	fmt.Println("accounts--------22222:\n", accounts)
	err = client.AccountManager.UnlockDefault(txConf.PassWord)
	if err != nil {
		txLog.LogE("Unlock failed! [%v]", err)
		return "", mpcCommon.NewError(511), "", ""
	}

	// accounts := client.AccountManager.List()
	// fmt.Println("accounts:\n", accounts)

	// err := client.AccountManager.UnlockDefault(txConf.PassWord)
	// if err != nil {
	// 	txLog.LogE("UnlockDefault failed! [%v]", err)
	// 	return "", mpcCommon.NewError(511)
	// }

	//get contract
	cfxContractAddr := cfxaddress.MustNew(contractAddr)
	instance, err := cfxerc1155.NewCfxerc1155(cfxContractAddr, client)
	if err != nil {
		txLog.LogE("NewCfxerc1155 failed! [%v]", err)
		return "", mpcCommon.NewError(511), "", ""
	}

	tx, hash, err := instance.SetApprovalForAll(nil, cfxApprovedOperator.MustGetCommonAddress(), flag)
	outTx := fmt.Sprintf("%v", tx)
	fmt.Println("outTx: ", outTx)
	if err != nil {
		txLog.LogE("Call contract SetApprovalForAll failed! [%v]", err)
		return "", mpcCommon.NewError(502), outTx, ""
	}
	fmt.Println("hash: ", hash)

	// logrus.WithField("tx", tx).WithField("hash", hash).Info("SetApproveForAllERC1155")
	receipt, err := client.WaitForTransationReceipt(*hash, time.Second)
	outRecipt := fmt.Sprintf("%v", receipt)
	fmt.Println("outRecipt: ", outRecipt)
	if err != nil {
		txLog.LogE("WaitForTransationReceipt failed! [%v]", err)
		return "", mpcCommon.NewError(514), outTx, outRecipt
	}

	// logrus.WithField("SetApproveForAllERC1155 receipt", receipt).Info()

	return hash.String(), mpcCommon.NewError(200), outTx, outRecipt
}

func SetApprovalForAll(reqChain, contractAddr, caller, approved string, flag bool) (string, mpcCommon.NftError, string, string) {
	nftContract, opts, nftErr := getNftContractTransaction(reqChain, contractAddr, caller)
	if !mpcCommon.Valid(nftErr) {
		txLog.LogE("Get nft contract and transaction options failed! [%v]", nftErr.ErrorMsg)
		return "", nftErr, "", ""
	}
	tx, err := nftContract.SetApprovalForAll(opts, common.HexToAddress(approved), flag)
	if err != nil {
		txLog.LogE("Call contract SetApprovalForAll failed! [%v]", err)
		return "", mpcCommon.NewError(502), "", ""
	}
	return tx.Hash().String(), mpcCommon.NewError(200), "", ""
}

// cfx 设置代付gas
func CfxSetSponsorForGas(reqChain, sponsorAddr, contractAddr, caller, callprivatekey, payableAmount, upperBound string) (string, mpcCommon.NftError, string, string) {

	// get cfx client
	client, nftErr := client.GetCfxClient(reqChain)
	if !mpcCommon.Valid(nftErr) {
		txLog.LogE("Get cfx client failed! [%v]", nftErr.ErrorMsg)
		return "", nftErr, "", ""
	}

	accounts := client.AccountManager.List()
	fmt.Println("accounts-----------------11111:\n", accounts)

	for _, account := range accounts {
		client.AccountManager.Delete(account, txConf.PassWord)
		fmt.Println("delete account:", account)
	}

	address, err := txConf.AccountManager.ImportKey(callprivatekey, txConf.PassWord)
	fmt.Println("import address: ", address)
	if err != nil {
		txLog.LogE("Cfx Import to keystore failed! [%v]", err)
		// return "", mpcCommon.NewError(511)
	}

	accounts = client.AccountManager.List()
	fmt.Println("accounts--------22222:\n", accounts)
	err = client.AccountManager.UnlockDefault(txConf.PassWord)
	if err != nil {
		txLog.LogE("Unlock failed! [%v]", err)
		return "", mpcCommon.NewError(511), "", ""
	}

	//get contract
	fmt.Println("sponsorAddr:", sponsorAddr)
	fmt.Println("contractAddr:", contractAddr)
	cfxSponsorAddr := cfxaddress.MustNew(sponsorAddr)
	instance, err := cfxsponsor.NewCfxsponsor(cfxSponsorAddr, client)
	if err != nil {
		txLog.LogE("NewCfxsponsor failed! [%v]", err)
		return "", mpcCommon.NewError(511), "", ""
	}

	tPayableAmount, ok := big.NewInt(0).SetString(payableAmount, 10)
	if !ok {
		txLog.LogE("Input payableAmount [%v] not correct!", payableAmount)
		return "", mpcCommon.NewError(406), "", ""
	}
	fmt.Println("before tPayableAmount:", tPayableAmount)
	tPayableAmount = tPayableAmount.Mul(tPayableAmount, big.NewInt(1e18))
	fmt.Println("after tPayableAmount:", tPayableAmount)

	tUpperBound, ok := big.NewInt(0).SetString(upperBound, 10)
	if !ok {
		txLog.LogE("Input upperBound [%v] not correct!", upperBound)
		return "", mpcCommon.NewError(407), "", ""
	}
	fmt.Println("tUpperBound:", tUpperBound)

	resDiv := big.NewInt(1).Div(tPayableAmount, tUpperBound)
	fmt.Println("resDiv:", resDiv)

	if resDiv.Cmp(big.NewInt(1000)) == -1 {
		txLog.LogE("Input payableAmount [%v] is too small or [%v] upperBound is too large!", payableAmount, upperBound)
		return "", mpcCommon.NewError(408), "", ""
	}

	// value := types.NewBigInt(uint64(tPayableAmount.Int64()))
	value := types.NewBigIntByRaw(tPayableAmount)
	fmt.Println("value-BigInt:", value)
	fmt.Println("value-toInt:", value.ToInt())

	// nonce := cfxContext.GetNextNonceAndIncrease()
	// fmt.Println("nonce:", nonce)

	// tContractAddr := common.HexToAddress(contractAddr)
	tContractAddr := cfxaddress.MustNew(contractAddr)

	fmt.Println("contractAddr:", contractAddr)
	fmt.Println("tContractAddr:", tContractAddr)
	fmt.Println("tContractAddr:", tContractAddr.MustGetCommonAddress())

	tx, hash, err := instance.SetSponsorForGas(&types.ContractMethodSendOption{
		Value: value,
		// Nonce: nonce,
	}, tContractAddr.MustGetCommonAddress(), tUpperBound)
	outTx := fmt.Sprintf("%v", tx)
	fmt.Println("outTx: ", outTx)
	if err != nil {
		txLog.LogE("Call contract SetSponsorForGas failed! [%v]", err)
		return "", mpcCommon.NewError(502), outTx, ""
	}
	fmt.Println("hash:", hash)

	// logrus.WithField("tx", tx).WithField("hash", hash).Info("CfxSetSponsorForGas")
	receipt, err := client.WaitForTransationReceipt(*hash, time.Second)
	outRecipt := fmt.Sprintf("%v", receipt)
	fmt.Println("outRecipt: ", outRecipt)
	if err != nil {
		txLog.LogE("WaitForTransationReceipt failed! [%v]", err)
		return "", mpcCommon.NewError(514), outTx, outRecipt
	}

	// logrus.WithField("CfxSetSponsorForGas receipt", receipt).Info()

	return hash.String(), mpcCommon.NewError(200), outTx, outRecipt
}

// cfx 设置代付 collateral
func CfxSetSponsorForCollateral(reqChain, sponsorAddr, contractAddr, caller, callprivatekey, payableAmount string) (string, mpcCommon.NftError, string, string) {

	// get cfx client
	client, nftErr := client.GetCfxClient(reqChain)
	if !mpcCommon.Valid(nftErr) {
		txLog.LogE("Get cfx client failed! [%v]", nftErr.ErrorMsg)
		return "", nftErr, "", ""
	}

	accounts := client.AccountManager.List()
	fmt.Println("accounts-----------------11111:\n", accounts)

	for _, account := range accounts {
		client.AccountManager.Delete(account, txConf.PassWord)
		fmt.Println("delete account:", account)
	}

	address, err := txConf.AccountManager.ImportKey(callprivatekey, txConf.PassWord)
	fmt.Println("import address: ", address)
	if err != nil {
		txLog.LogE("Cfx Import to keystore failed! [%v]", err)
		// return "", mpcCommon.NewError(511)
	}

	accounts = client.AccountManager.List()
	fmt.Println("accounts--------22222:\n", accounts)
	err = client.AccountManager.UnlockDefault(txConf.PassWord)
	if err != nil {
		txLog.LogE("Unlock failed! [%v]", err)
		return "", mpcCommon.NewError(511), "", ""
	}

	//get contract
	fmt.Println("sponsorAddr:", sponsorAddr)
	fmt.Println("contractAddr:", contractAddr)
	cfxSponsorAddr := cfxaddress.MustNew(sponsorAddr)
	instance, err := cfxsponsor.NewCfxsponsor(cfxSponsorAddr, client)
	if err != nil {
		txLog.LogE("NewCfxsponsor failed! [%v]", err)
		return "", mpcCommon.NewError(511), "", ""
	}

	tPayableAmount, ok := big.NewInt(0).SetString(payableAmount, 10)
	if !ok {
		txLog.LogE("Input payableAmount [%v] not correct!", payableAmount)
		return "", mpcCommon.NewError(406), "", ""
	}
	fmt.Println("before tPayableAmount:", tPayableAmount)
	tPayableAmount = tPayableAmount.Mul(tPayableAmount, big.NewInt(1e18))
	fmt.Println("after tPayableAmount:", tPayableAmount)

	value := types.NewBigIntByRaw(tPayableAmount)
	fmt.Println("value-BigInt:", value)
	fmt.Println("value-toInt:", value.ToInt())

	tContractAddr := cfxaddress.MustNew(contractAddr)

	fmt.Println("contractAddr:", contractAddr)
	fmt.Println("tContractAddr:", tContractAddr)
	fmt.Println("tContractAddr:", tContractAddr.MustGetCommonAddress())

	tx, hash, err := instance.SetSponsorForCollateral(&types.ContractMethodSendOption{
		Value: value,
		// Nonce: nonce,
	}, tContractAddr.MustGetCommonAddress())
	outTx := fmt.Sprintf("%v", tx)
	fmt.Println("outTx: ", outTx)
	if err != nil {
		txLog.LogE("Call contract SetSponsorForCollateral failed! [%v]", err)
		return "", mpcCommon.NewError(502), outTx, ""
	}
	fmt.Println("hash:", hash)
	receipt, err := client.WaitForTransationReceipt(*hash, time.Second)
	outRecipt := fmt.Sprintf("%v", receipt)
	fmt.Println("outRecipt: ", outRecipt)
	if err != nil {
		txLog.LogE("WaitForTransationReceipt failed! [%v]", err)
		return "", mpcCommon.NewError(514), outTx, outRecipt
	}
	return hash.String(), mpcCommon.NewError(200), outTx, outRecipt
}

// cfx 添加代付白名单
func CfxAddPrivilegeByAdmin(reqChain, sponsorAddr, contractAddr, caller, callprivatekey string, addresses []string) (string, mpcCommon.NftError, string, string) {

	// get cfx client
	client, nftErr := client.GetCfxClient(reqChain)
	if !mpcCommon.Valid(nftErr) {
		txLog.LogE("Get cfx client failed! [%v]", nftErr.ErrorMsg)
		return "", nftErr, "", ""
	}

	accounts := client.AccountManager.List()
	fmt.Println("accounts-----------------11111:\n", accounts)

	for _, account := range accounts {
		client.AccountManager.Delete(account, txConf.PassWord)
		fmt.Println("delete account:", account)
	}

	address, err := txConf.AccountManager.ImportKey(callprivatekey, txConf.PassWord)
	fmt.Println("import address: ", address)
	if err != nil {
		txLog.LogE("Cfx Import to keystore failed! [%v]", err)
		// return "", mpcCommon.NewError(511)
	}

	accounts = client.AccountManager.List()
	fmt.Println("accounts--------22222:\n", accounts)
	err = client.AccountManager.UnlockDefault(txConf.PassWord)
	if err != nil {
		txLog.LogE("Unlock failed! [%v]", err)
		return "", mpcCommon.NewError(511), "", ""
	}

	//get contract
	fmt.Println("sponsorAddr:", sponsorAddr)
	fmt.Println("contractAddr:", contractAddr)
	cfxSponsorAddr := cfxaddress.MustNew(sponsorAddr)
	instance, err := cfxsponsor.NewCfxsponsor(cfxSponsorAddr, client)
	if err != nil {
		txLog.LogE("NewCfxsponsor failed! [%v]", err)
		return "", mpcCommon.NewError(511), "", ""
	}

	tContractAddr := cfxaddress.MustNew(contractAddr)

	fmt.Println("contractAddr:", contractAddr)
	fmt.Println("tContractAddr:", tContractAddr)
	fmt.Println("tContractAddr:", tContractAddr.MustGetCommonAddress())
	tAddresses := make([]common.Address, 0)

	for _, address := range addresses {
		tAddress := cfxaddress.MustNew(address)
		tAddresses = append(tAddresses, tAddress.MustGetCommonAddress())
		// tAddress := common.HexToAddress(address)
		// tAddresses = append(tAddresses, tAddress)
		fmt.Println("address:", address)
	}
	tx, hash, err := instance.AddPrivilegeByAdmin(nil, tContractAddr.MustGetCommonAddress(), tAddresses)
	outTx := fmt.Sprintf("%v", tx)
	fmt.Println("outTx: ", outTx)
	if err != nil {
		txLog.LogE("Call contract AddPrivilegeByAdmin failed! [%v]", err)
		return "", mpcCommon.NewError(502), outTx, ""
	}
	fmt.Println("hash:", hash)
	receipt, err := client.WaitForTransationReceipt(*hash, time.Second)
	outRecipt := fmt.Sprintf("%v", receipt)
	fmt.Println("outRecipt: ", outRecipt)
	if err != nil {
		txLog.LogE("WaitForTransationReceipt failed! [%v]", err)
		return "", mpcCommon.NewError(514), outTx, outRecipt
	}
	return hash.String(), mpcCommon.NewError(200), outTx, outRecipt
}

// cfx 移除代付白名单
func CfxRemovePrivilegeByAdmin(reqChain, sponsorAddr, contractAddr, caller, callprivatekey string, addresses []string) (string, mpcCommon.NftError, string, string) {

	// get cfx client
	client, nftErr := client.GetCfxClient(reqChain)
	if !mpcCommon.Valid(nftErr) {
		txLog.LogE("Get cfx client failed! [%v]", nftErr.ErrorMsg)
		return "", nftErr, "", ""
	}

	accounts := client.AccountManager.List()
	fmt.Println("accounts-----------------11111:\n", accounts)

	for _, account := range accounts {
		client.AccountManager.Delete(account, txConf.PassWord)
		fmt.Println("delete account:", account)
	}

	address, err := txConf.AccountManager.ImportKey(callprivatekey, txConf.PassWord)
	fmt.Println("import address: ", address)
	if err != nil {
		txLog.LogE("Cfx Import to keystore failed! [%v]", err)
		// return "", mpcCommon.NewError(511)
	}

	accounts = client.AccountManager.List()
	fmt.Println("accounts--------22222:\n", accounts)
	err = client.AccountManager.UnlockDefault(txConf.PassWord)
	if err != nil {
		txLog.LogE("Unlock failed! [%v]", err)
		return "", mpcCommon.NewError(511), "", ""
	}

	//get contract
	fmt.Println("sponsorAddr:", sponsorAddr)
	fmt.Println("contractAddr:", contractAddr)
	cfxSponsorAddr := cfxaddress.MustNew(sponsorAddr)
	instance, err := cfxsponsor.NewCfxsponsor(cfxSponsorAddr, client)
	if err != nil {
		txLog.LogE("NewCfxsponsor failed! [%v]", err)
		return "", mpcCommon.NewError(511), "", ""
	}

	tContractAddr := cfxaddress.MustNew(contractAddr)

	fmt.Println("contractAddr:", contractAddr)
	fmt.Println("tContractAddr:", tContractAddr)
	fmt.Println("tContractAddr:", tContractAddr.MustGetCommonAddress())
	tAddresses := make([]common.Address, 0)

	for _, address := range addresses {
		tAddress := cfxaddress.MustNew(address)
		tAddresses = append(tAddresses, tAddress.MustGetCommonAddress())
		// tAddress := common.HexToAddress(address)
		// tAddresses = append(tAddresses, tAddress)
		fmt.Println("address:", address)
	}
	tx, hash, err := instance.RemovePrivilegeByAdmin(nil, tContractAddr.MustGetCommonAddress(), tAddresses)
	outTx := fmt.Sprintf("%v", tx)
	fmt.Println("outTx: ", outTx)
	if err != nil {
		txLog.LogE("Call contract RemovePrivilegeByAdmin failed! [%v]", err)
		return "", mpcCommon.NewError(502), outTx, ""
	}
	fmt.Println("hash:", hash)
	receipt, err := client.WaitForTransationReceipt(*hash, time.Second)
	outRecipt := fmt.Sprintf("%v", receipt)
	fmt.Println("outRecipt: ", outRecipt)
	if err != nil {
		txLog.LogE("WaitForTransationReceipt failed! [%v]", err)
		return "", mpcCommon.NewError(514), outTx, outRecipt
	}
	return hash.String(), mpcCommon.NewError(200), outTx, outRecipt
}

// 查询方法
func getNftContractForQuery(reqChain, contractAddr string) (*contract.Contract, mpcCommon.NftError) {
	client, nftErr := client.GetEthClient(reqChain)
	if !mpcCommon.Valid(nftErr) {
		txLog.LogE("Get eth client failed! [%v]", nftErr.ErrorMsg)
		return nil, nftErr
	}
	nftContract, err := contract.NewContract(common.HexToAddress(contractAddr), client)
	if err != nil {
		txLog.LogE("Get nft contract failed! [%v]", err)
		return nil, mpcCommon.NewError(506)
	}
	return nftContract, mpcCommon.NewError(200)
}

func Owner(reqChain, contractAddr string) (string, mpcCommon.NftError, string, string) {
	nftContract, nftErr := getNftContractForQuery(reqChain, contractAddr)
	if !mpcCommon.Valid(nftErr) {
		txLog.LogE("Get nft contract failed! [%v]", nftErr.ErrorMsg)
		return "", nftErr, "", ""
	}
	address, err := nftContract.Owner(&ethBind.CallOpts{})
	if err != nil {
		txLog.LogE("Call Owner func failed! [%v]", err)
		return "", mpcCommon.NewError(502), "", ""
	}
	return address.String(), mpcCommon.NewError(200), "", ""
}

func Name(reqChain, contractAddr string) (string, mpcCommon.NftError, string, string) {
	nftContract, nftErr := getNftContractForQuery(reqChain, contractAddr)
	if !mpcCommon.Valid(nftErr) {
		txLog.LogE("Get nft contract failed! [%v]", nftErr.ErrorMsg)
		return "", nftErr, "", ""
	}
	name, err := nftContract.Name(&ethBind.CallOpts{})
	if err != nil {
		txLog.LogE("Call name func failed! [%v]", err)
		return "", mpcCommon.NewError(502), "", ""
	}
	return name, mpcCommon.NewError(200), "", ""
}

func Symbol(reqChain, contractAddr string) (string, mpcCommon.NftError, string, string) {
	nftContract, nftErr := getNftContractForQuery(reqChain, contractAddr)
	if !mpcCommon.Valid(nftErr) {
		txLog.LogE("Get nft contract failed! [%v]", nftErr.ErrorMsg)
		return "", nftErr, "", ""
	}
	symbol, err := nftContract.Symbol(&ethBind.CallOpts{})
	if err != nil {
		txLog.LogE("Call symbol func failed! [%v]", err)
		return "", mpcCommon.NewError(502), "", ""
	}
	return symbol, mpcCommon.NewError(200), "", ""
}

func TokenUri(reqChain, contractAddr, tokenid string) (string, mpcCommon.NftError, string, string) {
	tid, ok := big.NewInt(0).SetString(tokenid, 10)
	if !ok {
		txLog.LogE("Input token id [%v] not correct!", tokenid)
		return "", mpcCommon.NewError(403), "", ""
	}
	nftContract, nftErr := getNftContractForQuery(reqChain, contractAddr)
	if !mpcCommon.Valid(nftErr) {
		txLog.LogE("Get nft contract failed! [%v]", nftErr.ErrorMsg)
		return "", nftErr, "", ""
	}
	uri, err := nftContract.TokenURI(&ethBind.CallOpts{}, tid)
	if err != nil {
		txLog.LogE("Call TokenUri func failed! [%v]", err)
		return "", mpcCommon.NewError(502), "", ""
	}
	return uri, mpcCommon.NewError(200), "", ""
}

func BalanceOf(reqChain, contractAddr, queryAddr string) (string, mpcCommon.NftError, string, string) {
	nftContract, nftErr := getNftContractForQuery(reqChain, contractAddr)
	if !mpcCommon.Valid(nftErr) {
		txLog.LogE("Get nft contract failed! [%v]", nftErr.ErrorMsg)
		return "0", nftErr, "", ""
	}
	balance, err := nftContract.BalanceOf(&ethBind.CallOpts{}, common.HexToAddress(queryAddr))
	if err != nil {
		txLog.LogE("Call BalanceOf func failed! [%v]", err)
		return "0", mpcCommon.NewError(502), "", ""
	}
	return balance.String(), mpcCommon.NewError(200), "", ""
}

func OwnerOf(reqChain, contractAddr, tokenid string) (string, mpcCommon.NftError, string, string) {
	tid, ok := big.NewInt(0).SetString(tokenid, 10)
	if !ok {
		txLog.LogE("Input token id [%v] not correct!", tokenid)
		return "", mpcCommon.NewError(403), "", ""
	}
	nftContract, nftErr := getNftContractForQuery(reqChain, contractAddr)
	if !mpcCommon.Valid(nftErr) {
		txLog.LogE("Get nft contract failed! [%v]", nftErr.ErrorMsg)
		return "", nftErr, "", ""
	}
	address, err := nftContract.OwnerOf(&ethBind.CallOpts{}, tid)
	if err != nil {
		txLog.LogE("Call OwnerOf func failed! [%v]", err)
		return "", mpcCommon.NewError(502), "", ""
	}
	return address.String(), mpcCommon.NewError(200), "", ""
}

func TotalSupply(reqChain, contractAddr string) (string, mpcCommon.NftError, string, string) {
	nftContract, nftErr := getNftContractForQuery(reqChain, contractAddr)
	if !mpcCommon.Valid(nftErr) {
		txLog.LogE("Get nft contract failed! [%v]", nftErr.ErrorMsg)
		return "0", nftErr, "", ""
	}
	total, err := nftContract.TotalSupply(&ethBind.CallOpts{})
	if err != nil {
		txLog.LogE("Call TotalSupply func failed! [%v]", err)
		return "0", mpcCommon.NewError(502), "", ""
	}
	return total.String(), mpcCommon.NewError(200), "", ""
}

func GetApproved(reqChain, contractAddr, tokenid string) (string, mpcCommon.NftError, string, string) {
	tid, ok := big.NewInt(0).SetString(tokenid, 10)
	if !ok {
		txLog.LogE("Input token id [%v] not correct!", tokenid)
		return "", mpcCommon.NewError(403), "", ""
	}
	nftContract, nftErr := getNftContractForQuery(reqChain, contractAddr)
	if !mpcCommon.Valid(nftErr) {
		txLog.LogE("Get nft contract failed! [%v]", nftErr.ErrorMsg)
		return "", nftErr, "", ""
	}
	approved, err := nftContract.GetApproved(&ethBind.CallOpts{}, tid)
	if err != nil {
		txLog.LogE("Call GetApproved func failed! [%v]", err)
		return "", mpcCommon.NewError(502), "", ""
	}
	return strings.ToLower(approved.Hex()), mpcCommon.NewError(200), "", ""
}

func IsApprovedForAll(reqChain, contractAddr, owner, approved string) (bool, mpcCommon.NftError) {
	nftContract, nftErr := getNftContractForQuery(reqChain, contractAddr)
	if !mpcCommon.Valid(nftErr) {
		txLog.LogE("Get nft contract failed! [%v]", nftErr.ErrorMsg)
		return false, nftErr
	}
	flag, err := nftContract.IsApprovedForAll(&ethBind.CallOpts{}, common.HexToAddress(owner), common.HexToAddress(approved))
	if err != nil {
		txLog.LogE("Call IsApprovedForAll func failed! [%v]", err)
		return false, mpcCommon.NewError(502)
	}
	return flag, mpcCommon.NewError(200)
}

// 查询交易信息
func QueryTransactionResult(reqChain, tx string) (int, mpcCommon.NftError) {
	client, nftErr := client.GetEthClient(reqChain)
	if !mpcCommon.Valid(nftErr) {
		txLog.LogE("Get eth client failed! [%v]", nftErr.ErrorMsg)
		return 0, nftErr
	}
	receipt, err := client.TransactionReceipt(context.Background(), common.HexToHash(tx))
	if err != nil {
		txLog.LogE("TransactionReceipt failed! [%v]", err)
		return 0, mpcCommon.NewError(502)
	}
	return int(receipt.Status), mpcCommon.NewError(200)
}
